﻿using System.Collections.Generic;
using System.Linq;
using Dataweb.NShape;
using Dataweb.NShape.Advanced;
using System.ComponentModel;
using System;

namespace cz.zcu.PreSti.Shapes
{
    public class TriggerArrow : PolylineBase, ITrigger
    {
        #region properties

        [Category("Appearance")]
        [Description("Defines the line cap appearance of the line's beginning.")]
        [PropertyMappingId(PropertyIdStartCapStyle)]
        [RequiredPermission(Permission.Present)]
        public ICapStyle StartCapStyle
        {
            get
            {
                if (StartCapStyleInternal == null && Template == null) throw new NShapeException("Property StartCapStyle is not set.");
                return StartCapStyleInternal == null ? ((TriggerArrow)Template.Shape).StartCapStyle : StartCapStyleInternal;
            }
            set
            {
                StartCapStyleInternal = (Template != null && value == ((TriggerArrow)Template.Shape).StartCapStyle) ? null : value;
            }
        }


        [Category("Appearance")]
        [Description("Defines the line cap appearance of the line's ending.")]
        [PropertyMappingId(PropertyIdEndCapStyle)]
        [RequiredPermission(Permission.Present)]
        public ICapStyle EndCapStyle
        {
            get
            {
                if (EndCapStyleInternal == null && Template == null) throw new NShapeException("Property EndCapStyle is not set.");
                return EndCapStyleInternal == null ? ((TriggerArrow)Template.Shape).EndCapStyle : EndCapStyleInternal;
            }
            set
            {
                EndCapStyleInternal = (Template != null && value == ((TriggerArrow)Template.Shape).EndCapStyle) ? null : value;
            }
        }

        #endregion

        protected override void InitializeToDefault(IStyleSet styleSet)
        {
            base.InitializeToDefault(styleSet);
            EndCapStyleInternal = styleSet.CapStyles.ClosedArrow;
        }

        public override Shape Clone()
        {
            Shape result = new TriggerArrow(Type, (Template)null);
            result.CopyFrom(this);
            return result;
        }

        public override void CopyFrom(Shape source)
        {
            base.CopyFrom(source);
        }
			

        protected internal TriggerArrow(ShapeType shapeType, Template template)
            : base(shapeType, template)
        {
        }

        protected internal TriggerArrow(ShapeType shapeType, IStyleSet styleSet)
			: base(shapeType, styleSet) {
		}

        #region ITrigger Members

        public bool IsFullyConnected()
        {
            IEnumerable<ShapeConnectionInfo> e1 = this.GetConnectionInfos(-1, null);
            IEnumerable<ShapeConnectionInfo> e2 = this.GetConnectionInfos(-2, null);
            if (e1.Count() == 0 || e2.Count() == 0) return false;
            ShapeConnectionInfo i1 = e1.First();
            ShapeConnectionInfo i2 = e2.First();
            if (i1.OtherShape != null && Symbols.IsControlPointEvent(((ISymbol)(i1.OtherShape)), i1.OtherPointId) &&
                i2.OtherShape != null && Symbols.IsControlPointAction(((ISymbol)(i2.OtherShape)), i2.OtherPointId)) return true;
            return false;
        }

        public bool IsDescendantConnected()
        {
            return this.IsConnected(1, null) != null;
        }

        public ISymbol GetDescendant()
        {
            return (ISymbol)(this.GetConnectionInfos(-2, null).First().OtherShape);
        }

        public int GetDelay()
        {
            TriggerModel model = (TriggerModel)this.ModelObject;
            return model.Delay;
        }

        public int GetConnectedShapeActionN()
        {
            IEnumerable<ShapeConnectionInfo> e = this.GetConnectionInfos(-2, null);
            if (e.Count() == 0) return 0;
            ShapeConnectionInfo info = e.First();
            return Symbols.ControlPointIdToActionN((ISymbol)(info.OtherShape), info.OtherPointId);
        }

        public int GetEventN()
        {
            IEnumerable<ShapeConnectionInfo> e = this.GetConnectionInfos(-1, null);
            if (e.Count() == 0) return 0;
            ShapeConnectionInfo info= e.First();
            return Symbols.ControlPointIdToEventN((ISymbol)(info.OtherShape), info.OtherPointId);
        }

        #endregion

        internal static Shape CreateInstance(ShapeType shapeType, Template template)
        {
            return new TriggerArrow(shapeType, template);
        }
    }

    public class TriggerModel : ModelObjectBase
    {
        private int delay = 0;

        private const int PropertyIdDelay = 1;

        private char securityDomainName = 'A';

        [Category("Presentation")]
        [Description("Delay of the next stimulus/component start in miliseconds.")]
        [PropertyMappingId(PropertyIdDelay)]
        public virtual int Delay
        {
            get
            {
                return delay;
            }
            set
            {
                delay = value;
            }
        }

        public static TriggerModel CreateInstance(ModelObjectType modelObjectType) {
			return new TriggerModel(modelObjectType);
		}


		protected internal TriggerModel(ModelObjectType modelObjectType)
			: base(modelObjectType) {
                this.terminalCount = 2;
		}


        protected internal TriggerModel(TriggerModel source)
			: base(source) {
            Delay = source.Delay;
            this.terminalCount = 2;
		}


		public override IModelObject Clone() {
            return new TriggerModel(this);
		}


		public override IEnumerable<MenuItemDef> GetMenuItemDefs() {
			throw new NotImplementedException();
		}


		public override void Connect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId) {
		}


		public override void Disconnect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId) {
		}

        public override char SecurityDomainName
        {
            get { return securityDomainName; }
            set
            {
                if (value < 'A' || value > 'Z')
                    throw new ArgumentOutOfRangeException("SecurityDomainName", "The domain qualifier has to be an upper case  ANSI letter (A-Z).");
                securityDomainName = value;
            }
        }


        #region IEntity Members

        public static new IEnumerable<EntityPropertyDefinition> GetPropertyDefinitions(int version)
        {
            foreach (EntityPropertyDefinition pi in ModelObjectBase.GetPropertyDefinitions(version))
                yield return pi;
            yield return new EntityFieldDefinition("Delay", typeof(int));

        }

        protected override void LoadFieldsCore(IRepositoryReader reader, int version)
        {
            base.LoadFieldsCore(reader, version);
            Delay = reader.ReadInt32();
        }

        protected override void SaveFieldsCore(IRepositoryWriter writer, int version)
        {
            base.SaveFieldsCore(writer, version);
            writer.WriteInt32(Delay);
        }

        #endregion

    }
}
